﻿using System;
using System.Collections.Generic;
using System.Text;

namespace MLForgeSharp.Models.UnsupervisedLearningModels.Clustering
{
    /// <summary>
    /// 层次聚类+
    /// </summary>
    public class HierClustModel
    {
        private double[][] data; // 数据集
        private int numClusters; // 目标簇数
        private List<List<int>> clusters; // 聚类结果

        public HierClustModel(int numClusters = 2)
        {
            this.numClusters = numClusters;
        }

        // 计算欧氏距离
        private double EuclideanDistance(double[] a, double[] b)
        {
            double sum = 0.0;
            for (int i = 0; i < a.Length; i++)
            {
                sum += Math.Pow(a[i] - b[i], 2);
            }
            return Math.Sqrt(sum);
        }

        // 计算簇间距离（单链法：最小距离）
        private double ClusterDistance(List<int> cluster1, List<int> cluster2)
        {
            double minDistance = double.MaxValue;
            foreach (int i in cluster1)
            {
                foreach (int j in cluster2)
                {
                    double distance = EuclideanDistance(data[i], data[j]);
                    if (distance < minDistance)
                    {
                        minDistance = distance;
                    }
                }
            }
            return minDistance;
        }

        // 训练模型
        public void Train(double[][] data)
        {
            this.data = data;
            int numSamples = data.Length;

            // 初始化每个样本为一个簇
            clusters = new List<List<int>>();
            for (int i = 0; i < numSamples; i++)
            {
                clusters.Add(new List<int> { i });
            }

            // 逐步合并簇
            while (clusters.Count > numClusters)
            {
                double minDistance = double.MaxValue;
                int cluster1Index = -1;
                int cluster2Index = -1;

                // 找到距离最近的两个簇
                for (int i = 0; i < clusters.Count; i++)
                {
                    for (int j = i + 1; j < clusters.Count; j++)
                    {
                        double distance = ClusterDistance(clusters[i], clusters[j]);
                        if (distance < minDistance)
                        {
                            minDistance = distance;
                            cluster1Index = i;
                            cluster2Index = j;
                        }
                    }
                }

                // 合并两个簇
                clusters[cluster1Index].AddRange(clusters[cluster2Index]);
                clusters.RemoveAt(cluster2Index);
            }
        }

        // 获取聚类结果
        public List<List<int>> GetClusters()
        {
            return clusters;
        }
    }

    // 示例程序
    public class HierClustModelExample
    {
        public HierClustModelExample()
        {
            // 示例数据
            double[][] data = new double[][]
        {
            new double[] { 1.0, 2.0 },
            new double[] { 1.1, 2.1 },
            new double[] { 1.2, 2.2 },
            new double[] { 10.0, 10.0 },
            new double[] { 10.1, 10.1 },
            new double[] { 10.2, 10.2 }
        };

            // 创建模型
            HierClustModel model = new HierClustModel(numClusters: 2);

            // 训练模型
            model.Train(data);

            // 获取聚类结果
            List<List<int>> clusters = model.GetClusters();

            // 打印聚类结果
            for (int i = 0; i < clusters.Count; i++)
            {
                System.Console.Write("簇 " + i + ": ");
                foreach (int index in clusters[i])
                {
                    System.Console.Write("(" + data[index][0] + ", " + data[index][1] + ") ");
                }
                System.Console.WriteLine();
            }
        }
    }
}
